/**
 * 提示文本框
 * 调用方法：
 */

import React, { ReactElement } from 'react';
import {
  DeviceEventEmitter,
  Animated,
  Easing,
  EmitterSubscription,
  View
} from 'react-native';

import { GLOBAL_LOADING, VIDEO_LOADING } from '../../constant';
import Notch, { NotchType } from '../Notch';
import { loading } from '../../constant/resource';
import styles from './style';
import navigator from '../../util/navigator';
import { getRouteType, RouteType } from '../../config/route';

interface LoadingProp {
  listenerKey?: string;
}

interface State {
  visible: boolean;
  needBack: boolean;
}

class Loading extends React.Component<LoadingProp, State> {
  public timer: Animated.CompositeAnimation | null = null;

  public subscription: EmitterSubscription | null = null;

  public spinValue: Animated.Value = new Animated.Value(0);

  public start: boolean = false;

  public constructor(props: LoadingProp) {
    super(props);

    this.state = {
      visible: false,
      needBack: false
    };
  }

  public componentDidMount(): void {
    const { listenerKey = GLOBAL_LOADING } = this.props;
    this.subscription = DeviceEventEmitter.addListener(
      listenerKey,
      ({ visible, needBack = false }: State): void => {
        this.setState({ visible, needBack }, (): void => {
          if (visible) {
            if (this.start) return;

            this.start = true;
            this.spin();
            return;
          }
          if (this.timer) {
            this.start = false;
            this.timer.stop();
          }
        });
      }
    );
  }

  public componentWillUnmount(): void {
    if (this.subscription) {
      this.subscription.remove();
    }
    if (this.timer) {
      this.start = false;
      this.timer.stop();
    }
  }

  public spin = (): void => {
    this.timer = Animated.loop(
      Animated.timing(this.spinValue, {
        toValue: 1, // 最终值 为1，这里表示最大旋转 360度
        duration: 1500,
        easing: Easing.linear,
        useNativeDriver: true
      })
    );
    this.timer.start();
  };

  public render(): ReactElement | null {
    const spinRotate = this.spinValue.interpolate({
      inputRange: [0, 1], // 输入值
      outputRange: ['0deg', '-360deg'] // 输出值
    });

    const { visible, needBack } = this.state;
    if (!visible) return null;

    const { listenerKey = GLOBAL_LOADING } = this.props;
    if (listenerKey === VIDEO_LOADING) {
      return (
        <View style={styles.container}>
          <View style={styles.content}>
            <Animated.Image
              source={loading}
              style={[styles.loading, { transform: [{ rotate: spinRotate }] }]}
            />
          </View>
        </View>
      );
    }

    const currentRoute = navigator.getCurrentRoute();
    const routeType = getRouteType(currentRoute.routeName);

    return (
      <Notch
        style={styles.container}
        type={
          routeType === RouteType.LandScape ? NotchType.Left : NotchType.Top
        }
      >
        {needBack ? (
          <View style={styles.content}>
            <Animated.Image
              source={loading}
              style={[styles.loading, { transform: [{ rotate: spinRotate }] }]}
            />
          </View>
        ) : (
          <Animated.Image
            source={loading}
            style={[styles.loading, { transform: [{ rotate: spinRotate }] }]}
          />
        )}
      </Notch>
    );
  }
}

export default Loading;
